<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Cron_m extends CI_Model {
	/**
     * 构造函数
     *
     * @access public
     * @return void
     */

	const SEPARATOR = '#*#';

    public function __construct()
    {
		parent::__construct();
		$this->load->model('City_m','city');
		$this->load->model('Site_m','site');
		$this->load->model('Goods_m','goods');
		$this->load->model('Category_m','category');
		$this->load->helper('array');
		$this->load->library('security');
		$this->load->helper('security');
    }

	public function craw_data($site_id){
		log_message('debug', "Craw data - START - site id <$site_id>");
		if ($site_id < 0){
			log_message('error', "Craw data - FAILED - site id <$site_id>");
			return FALSE;
		}

		$condition = array('id' => $site_id);
		$result = $this->site->get_site($condition);
		if (count($result) != 1){
			log_message("error", "Craw data - FAILED - did not return site object - site id <$site_id>");
			return FALSE;
		}
		$site_info = $result[0];
		if ($site_info){
			$xml_url = $site_info->xml_url;
			if (strlen($xml_url) > 0){
				$sxml = @simplexml_load_file(trim($xml_url));
				if ($sxml){
					$goods = $this->parse_xml_goods($sxml, $site_info);
					return $goods;
				}else{
					log_message("error", "Craw data - FAILED - did not return xml data - site id <$site_id>");
				}
			}else{
				log_message("error", "Craw data - FAILED - xml_url invalid - site id <$site_id>");
			}
		}
	}

	function check_time_out($start_time){
		if ($start_time == 0){
			return FALSE;
		}
		if (time() - $start_time > 35){
			return TRUE;
		} else {
			return FALSE;
		}
	}

	function import_goods($goods, $site_id, $start_time){
		if (!$goods){
			return FALSE;
		}

		log_message("error", "Craw " . count($goods) . " goods for site [$site_id]");
		$add_count = 0;
		$cap = $this->site->get_site_cap($site_id);
		$goods_count = $this->goods->get_site_total_goods_count($site_id);
		if ($cap === -1){
			$add_count = -1;
		} else {
			$add_count = $cap - $goods_count;
			if ($add_count < 1){
				$add_count = 0;
			}
		}
		$exist_goods = $this->get_exist_goods_by_site_id($site_id);
		foreach ($goods as $igood){
			$is_time_out = $this->check_time_out($start_time);
			if ($is_time_out){
				return FALSE;
			}
			$good = $this->_xss_clean_goods($igood);
			$good = $this->_censor_good_title_description($good);
			$check_res = $this->check_exist_item($exist_goods, $good);
			if ($check_res == 2){
				$exist_good = $exist_goods[trim($good["goods_url"])];
				$this->update_exist_good($good, $exist_good[$good['city_id']]);
			} elseif ($check_res == 1) {
				if ($add_count === 0){
					break;
				}
				$inserted_good_id = $this->insert_new_good($good);
				if ($inserted_good_id > 0){
					$exist_goods[trim($good["goods_url"])] = array();
					$exist_goods[trim($good["goods_url"])][$good['city_id']] = $inserted_good_id;
				}
				$add_count -= 1;
			} elseif ($check_res == 4) {
				$this->replace_all_items($good, $site_id);
			}
		}
		return TRUE;
	}

	function replace_all_items($good, $site_id){
		$this->db->where('site_id', $site_id);
		$this->db->where('goods_url', $good['goods_url']);
		$this->db->delete('goods');

		$inserted_good_id = $this->insert_new_good($good);
		if ($inserted_good_id > 0){
			$exist_goods[trim($good["goods_url"])] = array();
			$exist_goods[trim($good["goods_url"])][$good['city_id']] = $inserted_good_id;
		}
	}

	// 1 - insert new; 2 - non all; 4 - all; 8 - not update
	function check_exist_item($exist_goods, $good){
		if (count($exist_goods) > 0 && array_key_exists(trim($good["goods_url"]), $exist_goods)){
			$exist_good = $exist_goods[trim($good["goods_url"])];
				
			$is_exist = array_key_exists(intval($good['city_id']), $exist_good);
			$pos = array_key_exists(1, $exist_good);
			$replace_all = (1 == intval($good['city_id']));

			if($pos){
				return 8;
			} elseif ($replace_all){
				return 4;
			} elseif ($is_exist == TRUE){
				return 2;
			} else {
				return 1;
			}
		} else {
			return 1;
		}
	}

	function _xss_clean_goods($good){
		foreach ($good as $k => $value) {
			if ($value and is_string($value))
			{
				$good[$k] = xss_clean($value);
			}
		}
		return $good;
	}

	function _censor_good_title_description($good){
		$examine_keys = array("title", "merchant_addr", "description");
		foreach ($examine_keys as $key){
			$value = element($key, $good, "");
			if (strlen($value) > 0){
				if (preg_match(BAN_CONTENT, $value)){
					$good['is_publish'] = 2;
					break;
				}
			}
		}
		return $good;
	}

	function update_exist_good($igood, $exist_id){
		$igood = $this->process_category($igood);
		$this->db->where('id', $exist_id);
		$this->db->update('goods', $igood); 
	}

	function insert_new_good($igood){
		$igood["create_time"] = date("Y-m-d H:i:s", time());
		$igood = $this->process_category($igood);
		if ($this->db->insert("goods", $igood)){
			return $this->db->insert_id();
		}else{
			return -1;
		}
	}

	function process_category($good){
		$cat1 = element('cat_level1', $good);
		if (strlen($cat1) > 0) # API contains category info
		{
			$int_cat_1 = intval($cat1);
			if ($int_cat_1 > 0)
			{
				if ($int_cat_1 < 7) # category_id between 1 and 6
				{
					$CATOGORY_MAP = array(
						1 => 7,
						2 => 8,
						3 => 9,
						4 => 10,
						5 => 11,
						6 => 12
					);
					$good['cat_level2'] = $CATOGORY_MAP[$int_cat_1];
				}
				else  # Invalided category_id
				{
					$good['cat_level1'] = -1;
				}
			}
		}
		else
		{
			$good['cat_level1'] = -1;
		}
		return $good;
	}

	function get_exist_goods_by_site_id($site_id){
		$map = array();
		if ($site_id > 0){
			$query = $this->db->query("SELECT goods.goods_url, goods.city_id, goods.id FROM goods WHERE goods.site_id = $site_id ;");
			if ($query){
				foreach ($query->result() as $row){
					$goods_url = trim($row->goods_url);
					if (! array_key_exists($goods_url, $map)){
						$map[$goods_url] = array();
					}
					$map[$goods_url][$row->city_id] = $row->id;
				}
			}
		}
		return $map;
	}

	function parse_xml_goods($xml, $site_info){
		$api_id = $site_info->api_template_id;
		$site_id = $site_info->id;

		if ($api_id < 1){
			log_message("error", "Invalid api id <$api_id> in site id <$site_id>");
			return FALSE;
		}

		if ($site_id < 1){
			log_message("error", "Invalid site id: $site_id");
			return FALSE;
		}

		if (!$xml){
			log_message("error", "XML object invalid, api id: $api_id, site id: $site_id");
			return FALSE;
		}

		$api_map = $this->get_api_map($api_id);
		$goods_fields = $this->get_goods_fields();
		$xpath_prefix = $this->get_xpath_prefix($api_id);

		$goods = array();

		if (strlen($xpath_prefix) < 1){
			log_message("error", "Invalided xpath_prefix - api id: $api_id, site id: $site_id");
			return FALSE;
		}

		foreach ($xml->xpath($xpath_prefix) as $ixml){
			$single_good = array();
			// get all fields in goods table
			foreach ($goods_fields as $field){
				$api_map_info = element($field, $api_map, "");
				$node_name = trim(element('xpath', $api_map_info, ""));
				$default_value = trim(element('default_value', $api_map_info, ""));
				if (strlen($node_name) > 0){
					$xml_node_value = $this->get_xml_node_value($ixml, $node_name, $default_value);
					$node_action = trim(element('action', $api_map_info, ""));
					if (strlen($node_action) > 0){
						$xml_node_value = $this->process_xml_node_value($xml_node_value, $api_map_info, $single_good);
					}
					$single_good[$field] = $xml_node_value;
				}
			}
			$single_good["site_id"] = $site_id;
			$goods[] = $single_good;
		}
		return $goods;
	}

	function process_xml_node_value($xml_node_value, $api_map_info, $single_good){
		$node_action = element('action', $api_map_info, "");
		if (strlen($node_action) > 0){
			if ($node_action == "timestamp"){
				$datetime_format = trim(element('parameter', $api_map_info, "Y-m-d H:i:s"));
				return date($datetime_format, $xml_node_value);
			}elseif ($node_action == "lookup"){
				$lu_table = trim(element('parameter', $api_map_info, ""));
				if (strlen($lu_table) > 0){
					if ($lu_table == "city_info"){
						$pre_city = unserialize (PRE_CITY);
						if ( in_array($xml_node_value, $pre_city) ){
							return $this->city->get_city_id_whith_add($xml_node_value);
						} else {
							return -1;
						}
					}elseif ($lu_table == "category"){
						$category_map = $this->category->get_level_one_category();
						$category_id = element($xml_node_value, $category_map, "");
						if (strlen($category_id) == 0){
							$category_id = -1;  // default == -1
						}
						return $category_id;
					}
				}
			}elseif ($node_action == "substr"){
				return substr($xml_node_value, 0, -2);
			}elseif ($node_action == "calc"){
				if (intval($single_good['sale_price']) == 0){
					return 0;
				}else{
					return 10 * intval($single_good['sale_price']) / intval($single_good['original_price']);
				}
			}else{
				return "";
			}
		}
	}

	function get_xml_node_value($xml, $node_name, $default){
		$nodes = $xml->xpath($node_name);
		if (count($nodes) != 0){
			$ret = trim($nodes[0]);
			if (strlen($ret) > 0){
				return $ret;
			}
		}
		return $default;
	}

	function get_xpath_prefix($api_id){
		$xpath_prefix = "";
		if ($api_id > 0){
			$query = $this->db->query("SELECT xpath_prefix FROM api_template WHERE id = $api_id;");
			$result_row = $query->row();
			$xpath_prefix = $result_row->xpath_prefix;
		}
		return $xpath_prefix;
	}

	function get_api_map($api_id){
		if ($api_id > 0){
			$query = $this->db->query("SELECT api_key.db_key, api_key.default_value, api_map.xpath, api_map.parameter, api_map.action FROM api_map JOIN api_key on api_key.id = api_map.api_key_id WHERE api_template_id = $api_id AND api_map.status = 1;");
            $res_arr  = $query->result_array();
			if ($res_arr){
                $map = array();
				foreach ($query->result_array() as $row){
					$map[trim($row["db_key"])] = $row;
				}
                return $map;
			}			
		}
		return array();
	}

	function get_goods_fields(){
		$fields = array();
		$query = $this->db->query('DESC goods;');
		foreach ($query->result_array() as $row){
			if ($row["Field"] == "id"){
				continue;
			}
			$fields[] = $row["Field"];
		}
		return $fields;
	}


}

/* End of file cron_m.php */
/* Location: ./system/models/cron_m.php */
